#ifndef __NET_APP__
#define __NET_APP__

#include "../sqlite3/sqlite3.hpp"
#include "../platform/include/platform.hpp"

static const int MSG_PAGE = 252;
static const int MEM_SHARE = 8096*125; //分配1000kb 进行使用 1Mb的内存共享,就目前的设备的使用完全够用
enum MSG_QUEUE_TYPE{
    WEB_DESKTOP_USE_QUEUE=0x1,
    CLI_USE_QUEUE=0x2
};

enum CACHE_TYPE_E{
    CACHE_UPDATE = 0x1,
    CACHE_NO_CHANGE = 0x2,
    CACHE_FIRST_CREATE = 0x3
};

enum XSI_IPC_E{
    MSG_QUEUE=0x0, //消息队列
    SEM=0x1, //信号量
    SHM=0x2 //共享内存 效率最高
};

//是否需要建立缓存队列
struct msg_buf{ //256个字节
    long msg_type;
    char text[MSG_PAGE]; //正文中最大的缓冲区
};

class xsi_ipc{ //缺点是不可以被IO口复用使用,通用IO口的设置
public:
    xsi_ipc(){}
    xsi_ipc(const char* kp,int id,XSI_IPC_E t):key_path(kp),key_id(id),type(t){}
    void operator()(const char*kp,int id,XSI_IPC_E t);
    void xsi_ipc_init();
    void snd(msg_buf *buf,size_t size);
    void write(char*buf,int offset,int size);
    void read(char*buf,int offset,int size);
    void sem_p();
    void sem_v();
    void sem_del();
    void rcv(msg_buf *buf,size_t size);
    ~xsi_ipc(); //对现有的IPC 进程间使用的 IPC 键进行析构避免其他进程访问出错
private:
    XSI_IPC_E type;
    const char* key_path; //key_t 所使用的需要计算的路径
    int key_id; //key_t 需要计算的key id 的值的大小
    key_t xsi_ipc_key;
    int msg_queue_id;
    int shm_id;
    char* shm_addr;
    int sem_id;
};

//struct 默认的是private ,只有这一点和class 不相同
struct csv{
public:
    unsigned char mem_status; //当前内存页是否为更新的状态
    int cache_mem_offset;
    int id;
    char name[128];
    char value[100];
    char type[10];
    unsigned char mode;
    unsigned char attr; // 当前页的位置在缓存池中的的位置
    unsigned short pages_crc; //对页中的数据进行crc校验
};

//最大分页多分配一页,为了保证在共享内存中永远可以使用
struct cache_mem{
    #define MAX_PAGES ((MEM_SHARE)/sizeof(csv)+1)
    int begin_pages_empty_index;                        //  空的页表起始索引值
    int end_pages_empty_index;                          //  空的页表终止索引值
    int begin_pages_full_index=0;                         //  目前查询页的位置
    int end_pages_full_index;                           //  满页表索引位置
    csv* pages_index_record[MAX_PAGES];                 //  记录维护的cache_mem的空间,状态标志位,1,当前页正在被使用,-1,转台不明,0,未被使用
    csv* full_pages[MAX_PAGES];                         //  满页记录空间
    csv* empty_pages[MAX_PAGES];                        //  记录的空闲的的页
    unsigned short mem_crc_pages[MAX_PAGES];            //  原始CRC页表的使用
    csv pages[MAX_PAGES] = {0};                         //  抽象出来的缓存池
    int cavity_pages_cnt;                               //  空洞页计数
};

/*我对POSIX的标准库更有信心,前辈说,pthread库也是gnu posix 的标准库更出色*/
class cache_layer{ 
public:
    cache_layer(){}
    json* fp;
    cache_mem* zone; //缓存池(对应内核分区的概念)
    void ipc_init(void);
    void cache_read(char* buf);
    void cache_write(char* buf); //缓冲区的读写
    void update_cache_layer(); //更新缓冲区
    void cache_layer_info(); // 查看缓存层的信息
    CACHE_TYPE_E cache_status(); //TODO:决定是否更新缓冲层,这个是由app之间的交互决定的
    ~cache_layer();
private:
    std::string cache_name; // 缓存池的名字
    xsi_ipc sem; //用于进程之间对数据区域读写操作的互斥
    xsi_ipc shm; //用于将缓存层共享到内存当中
};

class app_layer{
public:
    app_layer(){}
    void operator()(json& f,platform_interface*p,cache_mem* t){
        this->fp = &f;
        this->plat_ptr = p;
        app_cache.fp = &f;
        app_cache.zone = t;
    }
    void app_init();
    void app_interface(); //TODO:具体的实现方式没有想好
    void app_cache_info();
private:
    cache_layer app_cache; //app 缓存区的配置和设置 目前只完成了common缓冲区的建立
    json* fp;
    Sqlite3 sqlite;
    platform_interface* plat_ptr;
};
#endif